home *** CD-ROM | disk | FTP | other *** search
/ PC World Interactive 7 / PC World Interactive 7.iso / program / cprog.EXE / OBJ2ASM.ZIP / OPROCESS.C < prev    next >
Text File  |  1991-12-20  |  39KB  |  1,257 lines

  1. #include <stdio.h>
  2. #include <string.h>
  3. #include "o.h"
  4.  
  5. extern dword data_offset;
  6. extern char *buff_end;
  7. extern char *buff_cur;
  8. extern char *buff_beg;
  9. extern char buff[];
  10.  
  11. /*
  12. ** Local Variables
  13. */
  14. static char     hex_comment[COMSIZE] = {0};
  15. static char     idb_buff[256];
  16. static char     dup_buff[256];
  17. static char     struc_buff[256];
  18. static char     structure_form[128];
  19. static NODE_T   *sex_node;
  20. static NODE_T   *data_node;
  21. static DAT_T    *data_rec;
  22. static int      record_overused = 0;
  23.  
  24. /*
  25. ** Local Prototypes
  26. */
  27. void pub_advance( void );
  28. void fix_advance( void );
  29. void lone_public( void );
  30. void data_byte( int );
  31. void pre_dups( long, int );
  32. int proc_idb( int, dword, int *, int, word *, dword *);
  33. int proc_label( void );
  34. int proc_fixup( void );
  35. int proc_normal( int );
  36. void iterated( DAT_T *, DAT_T * );
  37. void enumerated( DAT_T *, DAT_T *, int );
  38. void proc_drec( DAT_T *, DAT_T *, int );
  39. NODE_T *list_sex( NODE_T *, int );
  40.  
  41. void pub_advance()
  42. {
  43.     /*
  44.     ** Advance to next Publics record
  45.     */
  46.     pub_node = traverse( pub_node, RIGHT );
  47.     pub_rec = (PUB_T *)pub_node->data;
  48. }
  49.  
  50. void fix_advance()
  51. {
  52.     /*
  53.     ** Advance to next Fixup record
  54.     */
  55.     fix_node = traverse( fix_node, RIGHT );
  56.     fix_rec = (FIX_T *)fix_node->data;
  57. }
  58.  
  59. void hint_advance(void)
  60. {
  61.     /*
  62.     ** Advance to next Hint record
  63.     */
  64.     hint_node = traverse( hint_node, RIGHT );
  65.     hint_rec = (HINT_T *)hint_node->data;
  66. }
  67.  
  68. void lone_public()
  69. {
  70.     char    operand[80];
  71.     long    relative;
  72.  
  73.     if ( pass == 3 ) {
  74.         out_label( pub_rec->name );
  75.         out_directive( "=" );
  76.         if ( segment == 0 ) {
  77.             sprintf( operand, "0%04Xh", pub_rec->offset );
  78.         } else {
  79.             relative = (long)pub_rec->offset - inst_offset;
  80.             if ( relative < 0L ) {
  81.                 sprintf( operand, "$ - 0%04lXh", -relative );
  82.             } else {
  83.                 sprintf( operand, "$ + 0%04lXh", relative );
  84.             }
  85.         }
  86.         out_operand( operand );
  87.         out_endline();
  88.     }
  89. }
  90.  
  91. int data_check( offset )
  92.     word    offset;
  93. {
  94.     int             direct;
  95.  
  96.     /*
  97.     ** Are we at a public symbol?
  98.     */
  99.     pub_search.seg_idx = segment;
  100.     pub_search.offset  = inst_offset + offset;
  101.     direct = RIGHT;
  102.     while ( pub_node != public_tree
  103.             && (direct = pub_compare( &pub_search, pub_rec )) == LEFT ) {
  104.         lone_public();
  105.         pub_advance();
  106.     }
  107.     if ( direct == EQUAL ) {
  108.         return( LABEL );
  109.     }
  110.  
  111.     /*
  112.     ** Are we at a fix-up position?
  113.     */
  114.     fix_search.seg_idx    = segment;
  115.     fix_search.dat_offset = data_offset;
  116.     fix_search.offset     = (int)(inst_offset - data_offset) + offset;
  117.     direct = RIGHT;
  118.     while ( fix_node != fix_tree 
  119.             && (direct = fix_compare( &fix_search, fix_rec )) == LEFT ) {
  120.         fix_advance();
  121.     }
  122.     /* Are we on a fixup that is in the right position?  We can't just test
  123.     ** whether the "direct==EQUAL" because we could have fixups from the
  124.     ** next data record showing up.
  125.     */
  126.     if ( fix_rec->seg_idx == segment
  127.       && fix_rec->dat_offset + fix_rec->offset == inst_offset + offset ) {
  128.         return( FIXUP );
  129.     }
  130.     /*
  131.     ** Are we close to a public symbol? (prevents 2 byte operands)
  132.     */
  133.     if ( pub_node != public_tree 
  134.             && pub_rec->seg_idx == pub_search.seg_idx 
  135.             && pub_rec->offset  == pub_search.offset + 1 ) {
  136.         return( BAD );
  137.     }
  138.     /*
  139.     ** Are we close to a fix-up? (prevents 2 byte operands)
  140.     */
  141.     if ( fix_node != fix_tree
  142.       && fix_rec->seg_idx == segment
  143.       && fix_rec->dat_offset + fix_rec->offset == inst_offset + offset + 1 ) {
  144.         return( BAD );
  145.     }
  146.     return( 0 );
  147. }
  148.  
  149. void data_byte( size )
  150.     int     size;
  151. {
  152.     char    *opcode;
  153.     int     out_count;
  154.     int     times;
  155.     char    operand[50];
  156.     char    rev_buff[10];
  157.     char    temp[4];
  158.  
  159.     if ( last_pub_rec && pass == 3 ) {
  160.         if ( last_pub_rec->type == FAR ) {
  161.             out_directive("=");
  162.             out_operand("$");
  163.         }
  164.         if ( last_pub_rec->type == NEAR ) {
  165.             out_endline();
  166.         }
  167.     }
  168.  
  169.     opcode = size_to_opcode( size, × );
  170.  
  171.     while ( times ) {
  172.         out_count = 0;
  173.         strcpy( operand, "0" );
  174.         while ( out_count < size ) {
  175.             rev_buff[ out_count ] = (uchar)buff_regetc();
  176.             out_count++;
  177.         }
  178.         out_count = size;
  179.         while ( out_count ) {
  180.             --out_count;
  181.             sprintf( temp, "%02X", (uchar)rev_buff[out_count] );
  182.             strcat( operand, temp );
  183.         }
  184.         strcat( operand, "h" );
  185.         if ( pass == 3 ) {
  186.             out_directive( opcode );
  187.             out_operand( operand );
  188.             out_endline();
  189.         }
  190.         --times;
  191.     }
  192.     last_pub_rec = NULL;
  193. }
  194.  
  195. void pre_dups( count, orgable )
  196.     long    count;
  197.     int     orgable;
  198. {
  199.     char    *opcode;
  200.     char    *operand;
  201.     char    temp[80];
  202.     int     times;
  203.  
  204.     if ( last_pub_rec && pass == 3 ) {
  205.         if ( last_pub_rec->type == FAR ) {
  206.             out_directive("=");
  207.             out_operand("$");
  208.         }
  209.         if ( last_pub_rec->type == NEAR ) {
  210.             out_endline();
  211.         }
  212.     }
  213.  
  214.     if ( count != 0L ) {
  215.         if ( (orgable && inst_offset == 0 && count > 0L) || count < 0L ) {
  216.             opcode = "ORG";
  217.             sprintf( temp, "0%04Xh", inst_offset + count );
  218.             operand = temp;
  219.         } else {
  220.             if ( compatibility == 2 ) {
  221.                 operand = "1";                  /* Default operand */
  222.                 switch( (int)count ) {
  223.                     case 1:    opcode = "rb";  break;
  224.                     case 2:    opcode = "rw";  break;
  225.                     case 4:    opcode = "rd";  break;
  226.                     default:    opcode = "rs";
  227.                                 sprintf( temp, "0%04Xh", count );
  228.                                 operand = temp;
  229.                                 break;
  230.                 }
  231.             } else {
  232.                 operand = "1 dup (?)";          /* Default operand */
  233.  
  234.                 opcode = size_to_opcode( (int)count, × );
  235.  
  236.                 sprintf( temp, "%d dup(?)", times );
  237.                 operand = temp;
  238.             }
  239.         }
  240.         if ( pass == 3 && count != 0L ) {
  241.             out_directive( opcode );
  242.             out_operand( operand );
  243.             out_endline();
  244.         }
  245.         inst_offset += count;
  246.         last_pub_rec = NULL;
  247.     }
  248. }
  249.  
  250. int proc_idb( depth, mult, dup_only, extended, length_used, repeat_cnt )
  251.     int             depth;
  252.     dword   mult;
  253.     int             *dup_only;
  254.     int             extended;
  255.     word    *length_used;
  256.     dword   *repeat_cnt;
  257. {
  258.     dword   repeat;
  259.     word    num_blocks;
  260.     word    blocks;
  261.     word    length;
  262.     int             data;
  263.     word    data_size;
  264.     word    result;
  265.     int             fix_size;
  266.     char            operand[80];
  267.     uchar   rev_buff[10];
  268.     word    out_count;
  269.     int             dcheck;
  270.     int             dummy;
  271.  
  272.     result = 512;
  273.  
  274.     repeat = (dword)buff_regetc();
  275.     repeat += (dword)buff_regetc() << 8;
  276.     *length_used += 2;
  277.  
  278.     if ( extended ) {
  279.         repeat += (dword)buff_regetc() << 16;
  280.         repeat += (dword)buff_regetc() << 24;
  281.         *length_used += 2;
  282.     }
  283.     num_blocks = buff_regetc();
  284.     num_blocks += buff_regetc() << 8;
  285.     *length_used += 2;
  286.  
  287.     if ( repeat_cnt ) {             /* Return repeat count if needed */
  288.         *repeat_cnt = repeat;
  289.     }
  290.  
  291.     if ( repeat != 1 || num_blocks != 0 ) {
  292.         sprintf( idb_buff, "%ld dup(", repeat );
  293.         strcat( dup_buff, idb_buff );
  294.     }
  295.  
  296.     mult *= repeat;
  297.  
  298.     if ( num_blocks ) {
  299.         blocks = num_blocks;
  300.         while ( blocks ) {
  301.             if ( depth == 2 ) {
  302.                 *dup_only = TRUE;
  303.             }
  304.             data_size = proc_idb( depth+1, mult, dup_only, extended,
  305.                                                        length_used, NULL );
  306.             if ( data_size < result ) {
  307.                 result = data_size;
  308.             }
  309.             --blocks;
  310.             if ( blocks != 0 ) {
  311.                 strcat( dup_buff, "," );
  312.                 strcat( struc_buff, "," );
  313.             }
  314.         }
  315.     } else {
  316.         length = buff_regetc();
  317.         result = length;
  318.         *length_used += length + 1;         /* one extra for the length byte */
  319.         data_size = 0;
  320.         while ( length ) {
  321.             do {
  322.                 data = buff_getc();
  323.                 if ( data == EOF ) {
  324.                     break;
  325.                 }
  326.                 if ( data < ' ' || data > '~' ) {
  327.                     break;
  328.                 }
  329.                 data_size++;
  330.                 inst_offset += mult;
  331.                 dcheck = data_check( 0 );
  332.             } while ( *dup_only && (dcheck == NORMAL || dcheck == BAD) );
  333.             if ( *dup_only && data_size >= data_string ) {
  334.                 buff_reseek();
  335.                 length -= data_size;
  336.                 idb_buff[0] = '\'';
  337.                 out_count = 1;
  338.                 while ( data_size ) {
  339.                     data = buff_regetc();
  340.                     idb_buff[out_count++] = (char)data;
  341.                     --data_size;
  342.                 }
  343.                 idb_buff[out_count++] = '\'';
  344.                 idb_buff[out_count] = '\0';
  345.                 if ( depth != 1 ) {
  346.                     *dup_only = TRUE;
  347.                 }
  348.                 strcat( dup_buff, idb_buff );
  349.                 strcat( struc_buff, idb_buff );
  350.             } else {
  351.                 /*
  352.                 ** Was it a fixup?
  353.                 */
  354.                 inst_offset -= data_size * mult;
  355.                 buff_reseek();      /* Back to start, string look */
  356.                                     /* may have moved ptr         */
  357.                 if ( data_check( 0 ) == FIXUP ) {
  358.                     if ( depth != 1 ) {
  359.                         *dup_only = TRUE;
  360.                     }
  361.                     if ( fix_rec->form == POINTER ) {
  362.                         fix_size = get_fix( operand, 2, FALSE, segment_bytes,
  363.                                                     FAR, FALSE, &dummy, DS );
  364.                     } else {
  365.                         fix_size = get_fix( operand, 2, FALSE, segment_bytes,
  366.                                                     NEAR, FALSE, &dummy, DS );
  367.                     }
  368.                     inst_offset += fix_size * mult;
  369.                     length -= fix_size;
  370.                     if ( pass == 3 ) {
  371.                         strcat( dup_buff, operand );
  372.                         strcat( struc_buff, operand );
  373.                     }
  374.                     buff_empty();
  375.                 } else {
  376.                     /*
  377.                     ** Nope, not a string.  Leave one or multiple bytes
  378.                     */
  379.                     data_size = length;
  380.                     if ( data_size != 2 && data_size != 4 && data_size != 6
  381.                                         && data_size != 8 && data_size != 10 ) {
  382.                         data_size = 1;
  383.                     }
  384.                     strcat( dup_buff, "0" );
  385.                     if ( depth == 1 ) {
  386.                         strcat( struc_buff, "0" );
  387.                     }
  388.                     out_count = 0;
  389.                     while ( out_count < data_size ) {
  390.                         rev_buff[ out_count ] = (uchar)buff_regetc();
  391.                         out_count++;
  392.                     }
  393.                     out_count = data_size;
  394.                     while ( out_count ) {
  395.                         --out_count;
  396.                         if ( depth != 1 ) {
  397.                             if ( rev_buff[out_count] != 0 ) {
  398.                                 *dup_only = TRUE;
  399.                             }
  400.                         }
  401.                         sprintf( idb_buff, "%02X", rev_buff[out_count] );
  402.                         strcat( dup_buff, idb_buff );
  403.                         if ( depth == 1 ) {
  404.                             strcat( struc_buff, idb_buff );
  405.                         }
  406.                     }
  407.                     strcat( dup_buff, "h" );
  408.                     if ( depth == 1 ) {
  409.                         strcat( struc_buff, "h" );
  410.                     }
  411.  
  412.                     length -= data_size;
  413.                     inst_offset += mult * data_size;
  414.                 }
  415.             }
  416.             if ( length ) {
  417.                 strcat( dup_buff, "," );
  418.             }
  419.         }
  420.     }
  421.  
  422.     if ( repeat != 1 || num_blocks != 0 ) {
  423.         strcat( dup_buff, ")" );
  424.     }
  425.  
  426.     return( result );
  427. }
  428.  
  429.  
  430. int proc_label()
  431. {
  432.     char            text[50];
  433.     dword   past_seg;
  434.     char            *size_text;
  435.  
  436.     if ( pub_rec->type == FAR ) { 
  437.         size_text = "THIS FAR";
  438.     } else {
  439.         size_text = "THIS NEAR";
  440.     }
  441.  
  442.     if ( pass == 3 ) {
  443.         if ( pub_rec->offset >= seg_rec->length ) {
  444.             past_seg = pub_rec->offset - seg_rec->length;
  445.             if ( past_seg == 0 ) {
  446.                 strcpy( text, "$" );
  447.             } else {
  448.                 sprintf( text, "$ + 0%04Xh", size_text, past_seg );
  449.             }
  450.             out_line( pub_rec->name, "=", text, "" );
  451.         } else {
  452.             if ( pub_rec->type == FAR ) {
  453.                 out_line( pub_rec->name, "equ", "THIS FAR", "" );
  454.             } else {
  455.                 if ( pub_rec->type == NEAR ) {
  456.                     /* Put a colon ':' on labels within code segments */
  457.                     sprintf( text, "%s:", pub_rec->name );
  458.                     out_label( text );
  459.                 } else {
  460.                     out_label( pub_rec->name );
  461.                 }
  462.             }
  463.         }
  464.     }
  465.     last_pub_rec = pub_rec;
  466.     pub_advance();
  467.     if ( pub_rec->seg_idx == last_pub_rec->seg_idx 
  468.             && pub_rec->offset == last_pub_rec->offset ) {
  469.         if ( pass == 3 ) {
  470.             if ( last_pub_rec->type != NEAR ) {
  471.                 out_directive( "equ" );
  472.                 sprintf( text, "%s", size_text );
  473.                 out_operand( text );
  474.             }
  475.             out_endline();
  476.         }
  477.         proc_label();
  478.     }
  479.     return( 0 );
  480. }
  481.  
  482. int proc_fixup()
  483. {
  484.     int     fix_size;
  485.     int     fix_form;
  486.     int     fix_extended;
  487.     char    operand[100];
  488.     int     dummy;
  489.  
  490.     fix_form     = fix_rec->form;
  491.     fix_extended = fix_rec->extended;
  492.  
  493.     if ( fix_form == POINTER ) {
  494.         fix_size = get_fix( operand, 2, FALSE, segment_bytes,
  495.                                                     FAR, FALSE, &dummy, DS );
  496.     } else {
  497.         fix_size = get_fix( operand, 2, FALSE, segment_bytes,
  498.                                                     NEAR, FALSE, &dummy, DS );
  499.     }
  500.  
  501.     if ( pass == 3 ) {
  502.         if ( fix_form == OFFSET && fix_extended ) {
  503.             out_directive( "dd" );
  504.         } else {
  505.             if ( fix_form == POINTER && fix_extended ) {
  506.                 out_directive( "df" );
  507.             } else {
  508.                 out_directive( fix_type[fix_form].form );
  509.             }
  510.         }
  511.     }
  512.     inst_offset += fix_size;
  513.  
  514.     if ( pass == 3 ) {
  515.         out_operand( operand );
  516.         out_endline();
  517.     }
  518.     buff_empty();
  519.     if ( last_pub_rec ) {
  520.         last_pub_rec->type = size_to_type(fix_size);
  521.         last_pub_rec = NULL;
  522.     }
  523.     return( fix_size );
  524. }
  525.  
  526.  
  527. static void out_var(LOCAL_VAR*pVar)
  528. {
  529.   char *p;
  530.   char temp[50];
  531.   char text[80];
  532.  
  533.   sprintf(text, "\"%s\"",pVar->vname);
  534.   switch (pVar->class) {
  535.   case 7:
  536.        out_line("; (instance of typed variable)",text,"","");
  537.        return;
  538.   case 6:                           /* local typedef ? */
  539.        out_line("; (local typedef)", text, "","");
  540.        return;
  541.   case 4:                          /* register variable */
  542.        switch (pVar->bInfo1) {
  543.        case 0x06: p = "si"; break;
  544.        case 0x07: p = "di"; break;
  545.        default  : p = "[unknown]"; break;
  546.        }
  547.        sprintf(temp,": variable in register %s",p);
  548.        strcat(text, temp);
  549.        out_line(";",text,"","");
  550.        break;
  551.   case 2:                        /* variable */
  552.        if ((pVar->bInfo1&8)==8)
  553.          p = "argument";
  554.        else
  555.          p = "local";
  556.        sprintf(temp,": (var) %s stored in ",p);
  557.        strcat(text,temp);
  558.        switch (pVar->bInfo2) {
  559.        case 1 :                          /* stored on stack */
  560.             if ((int)pVar->wInfo1<0)
  561.               sprintf(temp,"[bp-%04X]",-pVar->wInfo1);
  562.             else
  563.               sprintf(temp,"[bp+%04X]",pVar->wInfo1);
  564.             break;
  565.        default :
  566.             strcpy(temp,"[unknown]");
  567.             break;
  568.        }
  569.        strcat(text,temp);
  570.        out_line(";",text,"","");
  571.        return;
  572.   case 0:                  /* static function */
  573.        out_line(";",temp," (static function) ","");
  574.   }
  575. }
  576.  
  577.  
  578. int proc_normal( inst_proc )
  579.     int     inst_proc;
  580. {
  581.     int      data_size;
  582.     int      data;
  583.     int      inst_length;
  584.     int      zeros;
  585.     int      string_limit;
  586.     int      dcheck;
  587.     char     temp[3];
  588.     int      this_size;
  589.     int      data_type;
  590.     int      direct;
  591.     LINE_T   Line, *pLine;
  592.     SCOPE_T  Scope, *pEndScope, *pArgScope, *pLocScope, *pScope;
  593.     NODE_T  *pNode;
  594.     LOCAL_VAR *pVar;
  595.  
  596.     data_type = UNKNOWN;
  597.     /*
  598.     ** Step 0, determine if there is a hint record at this position
  599.     */
  600.     hint_search.seg_idx    = segment;
  601.     hint_search.offset     = inst_offset;
  602.     direct = RIGHT;
  603.     while ( hint_node != hint_tree
  604.             && (direct = hint_compare( &hint_search, hint_rec )) == LEFT ) {
  605.         hint_advance();
  606.         direct = RIGHT;
  607.     }
  608.     if ( direct == EQUAL ) {
  609.         data_type = hint_rec->hint_type;
  610.     }
  611.  
  612.     if ( data_type == UNKNOWN ) {       /* Default, search for string */
  613.         /*
  614.         ** Step 1, Is it a string?
  615.         */
  616.         data_size = 0;
  617.         zeros = TRUE;
  618.         do {
  619.             data = buff_getc();
  620.             if ( data == EOF ) {
  621.                 break;
  622.             }
  623.             if ( data != 0 && data != 0x0A && data != 0x0D && data != 0x1B
  624.                   && (data < ' ' || data > '~') ) {
  625.                 break;
  626.             }
  627.             if ( data != 0 ) {
  628.                 zeros = FALSE;
  629.             }
  630.             data_size++;
  631.             inst_offset++;
  632.             dcheck = data_check( 0 );
  633.         } while ( dcheck == NORMAL || dcheck == BAD );
  634.  
  635.         if ( inst_proc ) {
  636.             string_limit = code_string;
  637.         } else {
  638.             string_limit = data_string;
  639.         }
  640.         if ( data_size >= string_limit || (zeros && data_size > 1) ) {
  641.             if ( last_pub_rec && last_pub_rec->type > FAR ) {
  642.                 this_size = type_to_size(last_pub_rec->type);
  643.                 if ( data_size < this_size ) {
  644.                     last_pub_rec->type = BYTE_PTR;
  645.                 }
  646.                 data_byte( this_size );
  647.                 buff_reseek();
  648.                 inst_offset -= data_size;
  649.                 inst_offset += this_size;
  650.                 last_pub_rec = NULL;
  651.                 return( this_size );
  652.             } else {
  653.                 /*
  654.                 ** Either near, far, or unknown
  655.                 */
  656.                 if ( last_pub_rec && pass == 3 ) {
  657.                     if ( last_pub_rec->type == FAR ) {
  658.                         out_directive("=");
  659.                         out_operand("$");
  660.                     }
  661.                     if ( last_pub_rec->type == NEAR ) {
  662.                         out_endline();
  663.                     }
  664.                 }
  665.                 empty_string( data_size );
  666.                 buff_reseek();
  667.                 last_pub_rec = NULL;
  668.                 return( data_size );
  669.             }
  670.         }
  671.         buff_reseek();
  672.         inst_offset -= data_size;
  673.     }
  674.  
  675.     if ( data_type == NEAR || (inst_proc && data_type == UNKNOWN) ) {
  676.         data = (uchar)buff_getc();
  677. #ifdef DEBUG
  678.         printf("Disassembly instruction lookup [%02X]\n", data );
  679. #endif
  680.         hex_finish = TRUE;
  681.  
  682.         inst_length = (*instr[data].rtn)
  683.                         ((uchar)data,
  684.                         instr[data].text,
  685.                         instr[data].special );
  686.         if ( inst_length == 0 ) {       /* Wrong, it wasn't an instruction */
  687.             data_type = UNKNOWN;
  688.         }
  689.     } else {
  690.         inst_length = 0;
  691.     }
  692.  
  693.     if ( inst_length ) {
  694.         /*
  695.         ** Check for instruction routine returning the proper number
  696.         ** of bytes eaten from buffer.
  697.         */
  698.         if ( buff_cur - buff_beg != inst_length ) {
  699. #ifdef DEBUG
  700.             printf("PN: Buffer remaining: %04d Length remaining: %04d\n",
  701.                                         buff_cur - buff_beg, inst_length );
  702. #endif
  703.             fmt_error("Disassembly Internal Instruction Processing" );
  704.         }
  705.  
  706.         /*
  707.         ** Yes, instruction, throw away buffer
  708.         */
  709.         if ( !*hex_comment ) {
  710.             Line.hex_offset = inst_offset;
  711.             pLine = find(&Line, line_tree, linnum_compare, NULL);
  712.             Scope.hex_offset = inst_offset+inst_length;
  713.             if (pass==3) {
  714.               pScope = pEndScope = find(&Scope, end_scope_tree, scope_compare, &pNode);
  715.               pArgScope = find(&Scope, arg_scope_tree, scope_compare, NULL);
  716.               pLocScope = find(&Scope, loc_scope_tree, scope_compare, NULL);
  717.               while (pScope && pEndScope->hex_offset == pScope->hex_offset) {
  718.                 out_comment("End of scope");
  719.                 pScope = pNode->ptr[LEFT]->data;
  720.                 pNode = pNode->ptr[LEFT];
  721.               }
  722.               if (pLocScope) {
  723.                 out_line("; Start of scope (locals)","","","");
  724.                 pVar = pLocScope->head;
  725.                 while (pVar) {
  726.                   out_var(pVar);
  727.                   pVar = pVar->next;
  728.                 }
  729.               }
  730.               if (pArgScope) {
  731.                 out_line("; Start of scope (arguments)","","","");
  732.                 pVar = pArgScope->head;
  733.                 while (pVar) {
  734.                   out_var(pVar);
  735.                   pVar = pVar->next;
  736.                 }
  737.               }
  738.             }
  739.             if (pLine)
  740.               sprintf(hex_comment, "[%05d] %04X: ", pLine->line_number, inst_offset);
  741.             else
  742.               sprintf(hex_comment, "        %04X: ", inst_offset );
  743.         }
  744.         this_size = inst_length;
  745.         while ( this_size-- ) {
  746.             sprintf( temp, "%02X", (uchar)buff_regetc() );
  747.             strcat( hex_comment, temp );
  748.         }
  749.         if ( hex_finish ) {
  750.             if ( pass == 3 ) {
  751.                 if ( hex_output ) {
  752.                     out_comment( hex_comment );
  753.                 }
  754.                 out_endline();
  755.             }
  756.             *hex_comment = 0;
  757.         }
  758.         inst_offset += inst_length;
  759.         if ( last_pub_rec ) {
  760.             if ( last_pub_rec->type != FAR ) {
  761.                 last_pub_rec->type = NEAR;
  762.             }
  763.             last_pub_rec = NULL;
  764.         }
  765.         return( inst_length );
  766.     }
  767.  
  768.     /*
  769.     ** Ingore any assumes that might have been pending
  770.     */
  771.     abort_assumes();
  772.  
  773.     /*
  774.     ** Nope, not instruction.  Leave byte
  775.     */
  776.     buff_reseek();      /* Back to start, instruction */
  777.                         /* look may have moved ptr    */
  778.     if ( last_pub_rec && last_pub_rec->type > FAR ) {
  779.         if ( last_pub_rec->type == UNKNOWN ) {
  780.             last_pub_rec->type = BYTE_PTR;      /* Default if not known */
  781.         }
  782.         if ( data_type == UNKNOWN ) {           /* Default if no hint */
  783.             data_type = last_pub_rec->type;
  784.         }
  785.         last_pub_rec->type = data_type;         /* Assign actual type */
  786.     } else {
  787.         if ( data_type == UNKNOWN ) {
  788.             data_type = BYTE_PTR;
  789.         }
  790.     }
  791.     data_size = type_to_size( data_type );
  792.     data_byte( data_size );
  793.     last_pub_rec = NULL;
  794.     inst_offset += data_size;
  795.     return( data_size );
  796. }
  797.  
  798. void iterated( data_rec, next_rec )
  799.     DAT_T   *data_rec;
  800.     DAT_T   *next_rec;
  801. {
  802.     char            temp[20];
  803.     word    length;
  804.     word    length_used;
  805.     PUB_T           *save_pub_rec;
  806.     int             dup_only;
  807.     int             dummy;
  808.     dword   repeat;
  809.     STRUC_T         *this_struc;
  810.  
  811.     length = data_rec->length;
  812.     fseek( o_file, data_rec->file_pos, L_SET );
  813.     length = buff_init( length );
  814.  
  815.     if ( data_check( 0 ) == LABEL ) {
  816.         proc_label();
  817.     }
  818.  
  819.     save_pub_rec = last_pub_rec;
  820.     if ( last_pub_rec ) {
  821.         if ( pass == 3 ) {
  822.             if ( last_pub_rec->type == FAR ) {
  823.                 out_directive("=");
  824.                 out_operand("$");
  825.             }
  826.             if ( last_pub_rec->type == NEAR ) {
  827.                 out_endline();
  828.             }
  829.         }
  830.     }
  831.  
  832.     /*
  833.     ** Process iterated data with this record
  834.     */
  835.     strcpy( structure_form, "" );
  836.     if ( data_rec->structure ) {
  837.         /* Processing for structures */
  838.         dup_only = FALSE;
  839.     } else {
  840.         if ( pass == 1 ) {
  841.             dup_only = FALSE;       /* Give 1 chance (pass 1) at structuring */
  842.         } else {
  843.             dup_only = TRUE;
  844.         }
  845.     }
  846.  
  847.     dup_buff[0]   = '\0';
  848.     strcpy( struc_buff, "<" );
  849.  
  850.     while ( length > 0 ) {
  851.         length_used = 0;
  852.         data_rec->size = proc_idb( 1, 1L, &dup_only, data_rec->extended,
  853.                                            &length_used, &repeat );
  854.         sprintf( temp, "(%ld,%1d)", repeat, size_to_type(data_rec->size) );
  855.         strcat( structure_form, temp );
  856.         length -= length_used;
  857.         if ( length ) {
  858.             strcat( dup_buff, "," );
  859.             strcat( struc_buff, "," );
  860.         }
  861.     }
  862.  
  863.     if ( dup_only ) {
  864.         if ( save_pub_rec ) {
  865.             save_pub_rec->type = size_to_type( data_rec->size );
  866.         }
  867.         if ( pass == 3 ) {
  868.             out_directive( size_to_opcode(data_rec->size, &dummy) );
  869.             out_operand( dup_buff );
  870.             out_endline();
  871.         }
  872.     } else {
  873.         /*
  874.         ** Its a structure!
  875.         */
  876.         strcat( struc_buff, ">" );
  877.  
  878.         if ( pass == 1 ) {
  879.             data_rec->structure = struc_insert( structure_form );
  880.         }
  881.  
  882.         this_struc = data_rec->structure;
  883.  
  884.         if ( save_pub_rec ) {
  885.             save_pub_rec->structure = this_struc;
  886.         }
  887.  
  888.         if ( pass == 3 ) {
  889.             sprintf( temp, "struct_%d", this_struc->index );
  890.             out_directive( temp );
  891.             out_operand( struc_buff );
  892.             out_endline();
  893.         }
  894.     }
  895.  
  896.     next_rec = next_rec;       /* Prevent unused variable warnings */
  897. }
  898.  
  899.  
  900. void enumerated( data_rec, next_rec, inst_proc )
  901.     DAT_T           *data_rec;
  902.     DAT_T           *next_rec;
  903.     int             inst_proc;
  904. {
  905.     int             length;
  906.     int             result;
  907.     dword   prev_offset;
  908.     int             addition;
  909.     int             dcheck;
  910.  
  911.     /*
  912.     ** Process enumerated data within this record
  913.     */
  914.     length = data_rec->length;
  915.     fseek( o_file, data_rec->file_pos+record_overused, L_SET );
  916.     length = buff_init( length-record_overused );
  917.     addition = 0;
  918.     if ( next_rec ) {
  919.         fseek( o_file, next_rec->file_pos, L_SET );
  920.         addition = 0x10;      /* Longest instruction can be 0x10 bytes long */
  921.         if ( addition > next_rec->length ) {
  922.             addition = next_rec->length;
  923.         }
  924.         length += buff_add( addition );
  925.     }
  926.     while ( length > addition ) {
  927. #ifdef DEBUG
  928.         printf( "DIS-ASSEMBLY processing enumerated %08lX %04X %04X %04X %04X\n", 
  929.                     data_rec, data_rec->offset, data_rec->length, length, 
  930.                     inst_offset );
  931. #endif
  932.         if ( length < 0 ) {
  933.             fmt_error( "Dis-assembly Record Over-run" );
  934.         }
  935.  
  936.         prev_offset = inst_offset;
  937.  
  938.         dcheck = data_check( 0 );
  939.  
  940.         switch ( dcheck ) {
  941.             case BAD:       result = proc_normal( inst_proc );      break;
  942.             case LABEL:     result = proc_label();                  break;
  943.             case FIXUP:     result = proc_fixup();                  break;
  944.             case NORMAL:    result = proc_normal( inst_proc );      break;
  945.         }
  946.  
  947.         length -= result;
  948.  
  949.         if ( (dword)result != inst_offset - prev_offset ) {
  950. #ifdef DEBUG
  951.             printf("Instruction Length was %ld, delta IP = %ld\n",
  952.                                    (long)result, inst_offset - prev_offset );
  953. #endif
  954.             fmt_error("Dis-assembly Instruction Size Error");
  955.         }
  956.  
  957.         if ( data_rec->offset + data_rec->length - length + addition 
  958.                                                         != inst_offset ) {
  959.             fmt_error("Dis-assembly Instruction Mis-alignment");
  960.         }
  961.  
  962.         if ( buff_end - buff_cur != length ) {
  963. #ifdef DEBUG
  964.             printf("Buffer remaining: %04d Length remaining: %04d\n", 
  965.                                             buff_end - buff_cur, length );
  966. #endif
  967.             fmt_error("Dis-assembly Internal Instruction Processing" );
  968.         }
  969.     }
  970.     record_overused = addition - length;
  971. }
  972.  
  973. void proc_drec( data_rec, next_rec, inst_proc )
  974.     DAT_T   *data_rec;
  975.     DAT_T   *next_rec;
  976.     int     inst_proc;
  977. {
  978.     int     orgable;
  979.  
  980. #ifdef DEBUG
  981.     printf("DIS-ASSEMBLY offset %04X\n", data_rec->offset );
  982. #endif
  983.     if ( pass == 3 ) {
  984.         out_newline();
  985.     }
  986.     /*
  987.     ** Do we need an ORG statement or dup(?)'s ?
  988.     */
  989.     if ( inst_offset != data_rec->offset+record_overused ) {
  990.         pub_search.seg_idx = segment;
  991.         pub_search.offset = data_rec->offset+record_overused;
  992.         orgable = TRUE;
  993.         while ( pub_node != public_tree 
  994.                 && pub_compare(&pub_search,pub_rec) == LEFT ) {
  995.             pre_dups( pub_rec->offset - inst_offset, orgable );
  996.             proc_label();
  997.             orgable = FALSE;
  998.         }
  999.         pre_dups( data_rec->offset+record_overused - inst_offset, orgable );
  1000.     }
  1001.     data_offset = data_rec->offset;
  1002.  
  1003.     switch( data_rec->type ) {
  1004.         case ENUMERATED:
  1005.             enumerated( data_rec, next_rec, inst_proc );
  1006.             break;
  1007.         case ITERATED:
  1008.             iterated( data_rec, next_rec );
  1009.             break;
  1010.     }
  1011. }
  1012.  
  1013.  
  1014. NODE_T *list_sex( node, seg_num )
  1015.     NODE_T  *node;
  1016.     int     seg_num;
  1017. {
  1018.     SEX_T   *sex_rec;
  1019.     EXT_T   *ext_rec;
  1020.  
  1021.     sex_rec = (SEX_T *)node->data;
  1022.     while ( node != sex_tree && sex_rec->seg_index < seg_num ) {
  1023.         node = traverse( node, RIGHT );
  1024.         sex_rec = (SEX_T *)node->data;
  1025.     }
  1026.     out_newline();
  1027.     while ( node != sex_tree && sex_rec->seg_index == seg_num ) {
  1028.         ext_rec = sex_rec->ext_rec;
  1029.         if ( ext_rec->used == seg_num ) {       /* Still in this segment? */
  1030.             print_ext( sex_rec->ext_rec );
  1031.         }
  1032.         node = traverse( node, RIGHT );
  1033.         sex_rec = (SEX_T *)node->data;
  1034.     }
  1035.     return( node );
  1036. }
  1037.  
  1038. void process_segment(void)
  1039. {
  1040.     NAME_T          *name_rec;
  1041.     DAT_T           *next_rec;
  1042.     int             inst_proc;
  1043.     int             seg_reg;
  1044.  
  1045.     segment = seg_rec->index;
  1046.  
  1047.     /*
  1048.     ** Skip segments which have no data, no external definitions,
  1049.     ** and no public symbols
  1050.     */
  1051.     if ( seg_rec->length == 0
  1052.   && (sex_node == sex_tree || ((SEX_T *)sex_node->data)->seg_index > segment)
  1053.   && (pub_node == public_tree || ((PUB_T *)pub_node->data)->seg_idx > segment)
  1054.         ) {
  1055.         return;
  1056.     }
  1057.  
  1058.     for ( seg_reg = 0; seg_reg < MAX_SEG_REGS; seg_reg++ ) {
  1059.         seg_rec->new_mode [seg_reg] = 0;
  1060.         seg_rec->new_index[seg_reg] = 0;
  1061.         seg_rec->prv_mode [seg_reg] = 0;
  1062.         seg_rec->prv_index[seg_reg] = 0;
  1063.     }
  1064.  
  1065.     /* Move to the hint records for this segment */
  1066.     while ( hint_node != hint_tree && hint_rec->seg_idx < segment ) {
  1067.         hint_node = traverse( hint_node, RIGHT );
  1068.     }
  1069.  
  1070.     name_search.index = seg_rec->name;      /* Look up segment name */
  1071.     name_rec = find( &name_search, name_tree, TC name_compare, NULL );
  1072.     if ( name_rec == NULL ) fmt_error( "Lost Code Segment Name (Oops!)" );
  1073.     cseg_name = name_rec->name;
  1074.  
  1075. #ifdef DEBUG
  1076.     printf("DIS-ASSEMBLY pass %d: segment %s\n", pass, cseg_name);
  1077. #endif
  1078.  
  1079.     if ( seg_rec->bit32 ) {
  1080.         segment_mode = 386;
  1081.     } else {
  1082.         segment_mode = 286;
  1083.     }
  1084.  
  1085.     if ( segment_mode == 386 ) {
  1086.         segment_bytes = 4;
  1087.     } else {
  1088.         segment_bytes = 2;
  1089.     }
  1090.  
  1091.     if ( pass == 3 ) {
  1092.         out_newline();
  1093.         if ( seg_rec->code ) {
  1094.             if ( compatibility == 2 ) {
  1095.                 out_line( cseg_name, "CSEG", "", "" );
  1096.             } else {
  1097.                 out_line( cseg_name, "SEGMENT", "", "" );
  1098.                 seg_rec->new_mode[1] = SEGMENT;     /* Default assume for CS: */
  1099.                 seg_rec->new_index[1] = segment;
  1100.                 adjust_assumes();
  1101.             }
  1102.         } else {
  1103.             if ( compatibility == 2 ) {
  1104.                 if ( stricmp(seg_rec->class->name,"CODE") == 0 ) {
  1105.                     out_line( cseg_name, "CSEG", "", "" );
  1106.                 } else
  1107.                 if ( stricmp(seg_rec->class->name,"DATA") == 0 ) {
  1108.                     out_line( cseg_name, "DSEG", "", "" );
  1109.                 } else
  1110.                 if ( stricmp(seg_rec->class->name,"STACK") == 0 ) {
  1111.                     out_line( cseg_name, "SSEG", "", "" );
  1112.                 } else
  1113.                 if ( stricmp(seg_rec->class->name,"EXTRA") == 0 ) {
  1114.                     out_line( cseg_name, "ESEG", "", "" );
  1115.                 } else {
  1116.                     out_line( cseg_name, seg_rec->class->name, "", "" );
  1117.                 }
  1118.             } else {
  1119.                 out_line( cseg_name, "SEGMENT", "", "" );
  1120.             }
  1121.         }
  1122.         sex_node = list_sex( sex_node, segment );   /* List local extrns */
  1123.     }
  1124.  
  1125. #if 0
  1126.     sprintf( operand, "; Segment mode is %d\n", segment_mode );
  1127.     if ( pass == 3 ) {
  1128.         out_line( "", operand, "", "" );
  1129.     }
  1130. #endif
  1131.  
  1132.     inst_proc = seg_rec->code;
  1133.  
  1134.     last_pub_rec = NULL;
  1135.     inst_offset = 0;                        /* Start at beginning of seg */
  1136.  
  1137.     inst_init();
  1138.  
  1139.     /*
  1140.     ** Loop through all data records for this segment
  1141.     */
  1142.     if ( data_node != data_tree ) {
  1143.         while ( data_rec->seg_idx == segment ) {
  1144.             /*
  1145.             ** Advance to next data record
  1146.             */
  1147.             data_node = traverse( data_node, RIGHT );
  1148.             /*
  1149.             ** Check if we can process this record with extra bytes from
  1150.             ** the next record.  This is to catch any instructions which
  1151.             ** span the record edges. (Only for ENUMERATED records)
  1152.             */
  1153.             next_rec = (DAT_T *)data_node->data;
  1154.             if ( data_node != data_tree && data_rec->type == ENUMERATED &&
  1155.                     next_rec->type == ENUMERATED &&
  1156.                     next_rec->seg_idx == segment && 
  1157.                     data_rec->offset + data_rec->length == next_rec->offset ) {
  1158.                 proc_drec( data_rec, next_rec, inst_proc );
  1159.             } else {
  1160.                 proc_drec( data_rec, NULL, inst_proc );
  1161.             }
  1162.             data_rec = next_rec;
  1163.         }
  1164.     }
  1165.  
  1166.     if ( pass == 3 && pub_rec->seg_idx == segment ) {
  1167.         out_newline();                  /* Blank line before trailings */
  1168.     }
  1169.     while ( pub_rec->seg_idx == segment ) {
  1170.         pre_dups( pub_rec->offset - inst_offset, FALSE );
  1171.         proc_label();
  1172.     }
  1173.  
  1174.     pre_dups( seg_rec->length - inst_offset, FALSE );
  1175.         
  1176.     if ( pass == 3 ) {
  1177.         out_newline();
  1178.         if ( compatibility == 2 ) {
  1179.         } else {
  1180.             out_line( cseg_name, "ENDS", "", "" );
  1181.         }
  1182.     }
  1183. }
  1184.  
  1185.  
  1186. void process()
  1187. {
  1188.     NODE_T          *seg_node;
  1189.     char            text[80];
  1190.     int             dummy;
  1191.  
  1192.     pub_node  = start( public_tree, RIGHT );    /* Start at beginning of */
  1193.     pub_rec   = (PUB_T *)pub_node->data;        /* Public symbols list   */
  1194.  
  1195.     fix_node  = start( fix_tree, RIGHT );       /* Start at beginning of */
  1196.     fix_rec   = (FIX_T *)fix_node->data;        /* Fixup records list    */
  1197.  
  1198.     data_node = start( data_tree, RIGHT );      /* Start at beginning of */
  1199.     data_rec = (DAT_T *)data_node->data;        /* Data record list      */
  1200.  
  1201.     hint_node  = start( hint_tree, RIGHT );     /* Start at beginning of */
  1202.     hint_rec   = (HINT_T *)hint_node->data;     /* Hints list            */
  1203.  
  1204.     sex_node = start( sex_tree, RIGHT );        /* Start at beginning of */
  1205.  
  1206.     if ( pass == 3 && !processor_type_comment_occurred ) {
  1207.         out_line( "", ".286p", "", "" );
  1208.         out_line( "", ".287", "", "" );
  1209.         processor_mode = 286;
  1210.     }
  1211.  
  1212.     /*
  1213.     ** Display all defined public values ( segment == 0 )
  1214.     */
  1215.     segment = 0;
  1216.     if ( pass == 3 && pub_rec->seg_idx == segment ) {
  1217.         out_newline();                  /* Blank line before trailings */
  1218.     }
  1219.     while ( pub_rec->seg_idx == segment ) {
  1220.         lone_public();                  /* Finish off any trailing */
  1221.         pub_advance();                  /* lone public labels      */
  1222.     }
  1223.  
  1224.     /*
  1225.     ** Loop through all segments
  1226.     */
  1227.     segment_mode = processor_mode;
  1228.     seg_node = start( segment_tree, RIGHT );
  1229.     while ( seg_node != segment_tree ) {
  1230.         seg_rec = (SEG_T *)seg_node->data;
  1231.         process_segment();
  1232.         seg_node = traverse( seg_node, RIGHT );
  1233.     }
  1234.  
  1235.     /*
  1236.     ** Finish off this module
  1237.     */
  1238.     fix_search.seg_idx    = 0;
  1239.     fix_search.dat_offset = 0;
  1240.     fix_search.offset     = 1;          /* Look for MODEND record */
  1241.  
  1242.     fix_rec = (FIX_T *)find( (char *)&fix_search, fix_tree, TC fix_compare, NULL );
  1243.     if ( fix_rec == NULL ) {
  1244.         if ( pass == 3 ) {
  1245.             out_newline();
  1246.             out_opcode("END");
  1247.             out_newline();
  1248.         }
  1249.     } else {
  1250.         get_target( text, fix_rec, 0, 0L, FALSE, 0, FALSE, &dummy, CS );
  1251.         if ( pass == 3 ) {
  1252.             out_newline();
  1253.             out_line( "", "END", text, "Module starting address" );
  1254.         }
  1255.     }
  1256. }
  1257.